! git log -1 --format="%H"
import sys
# Install gurobi
!{sys.executable} -m pip install -i https://pypi.gurobi.com gurobipy
!{sys.executable} -m pip install plotly geopy
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas as pd
from itertools import product
import gurobipy as gp
from gurobipy import GRB, quicksum
# These are ours
import problem
import visualization
Looking in indexes: https://pypi.gurobi.com Requirement already satisfied: gurobipy in /opt/anaconda3/lib/python3.8/site-packages (9.1.1) Requirement already satisfied: plotly in /opt/anaconda3/lib/python3.8/site-packages (4.14.3) Requirement already satisfied: geopy in /opt/anaconda3/lib/python3.8/site-packages (2.1.0) Requirement already satisfied: retrying>=1.3.3 in /opt/anaconda3/lib/python3.8/site-packages (from plotly) (1.3.3) Requirement already satisfied: six in /opt/anaconda3/lib/python3.8/site-packages (from plotly) (1.15.0) Requirement already satisfied: geographiclib<2,>=1.49 in /opt/anaconda3/lib/python3.8/site-packages (from geopy) (1.50)
def normalize(i, j):
assert i != j
return (i, j) if i < j else (j, i)
from model import Autonomax, Config
# Run on the first |C| cities (mostly for testing)
C = 41
# What scenario we will be utilizing
scenario = 0
# The number of cities in the core net
NC = 6
# 1 if the core net should be a cycle; 0 if it shoul be a path.
Z = 1
autonomax = Autonomax(
Config(
cities=problem.cities[:C],
distances=problem.D[:C, :C],
demand=problem.B[scenario][:C],
core_city_count=NC,
core_net_is_cycle=Z,
)
)
Academic license - for non-commercial use only - expires 2021-05-15 Using license file /Users/sjurwold/gurobi.lic
A = autonomax.model.getA()
count = lambda d: len(d) if isinstance(d, gp.tupledict) else 1
V = sum(count(v) for v in autonomax.variables.values())
C = sum(count(c) for c in autonomax.constraints.values())
print(f'V = {V}, C = {C}')
fig, ax = plt.subplots(1, figsize=(128, 128 * C/V))
ax.set_xticklabels([])
ax.set_yticklabels([])
plt.spy(A)
total = 0
print(f'\nCONSTRAINT SETS:')
for (name, constraint) in autonomax.constraints.items():
constraints_in_set = count(constraint)
print(f'{constraints_in_set:>5} | {name}')
#plt.gcf().text(0.07, 0.69 - 0.4 * (total + 0.5 * count(constraint)) / C, name, fontsize=14)
total += constraints_in_set
plt.plot([0, V], [total - 0.5, total - 0.5], color='grey')
total = 0
print(f'\nVARIABLE SETS:')
for (name, variables) in autonomax.variables.items():
variables_in_set = count(variables)
print(f'{variables_in_set:>5} | {name}')
#plt.gcf().text(0.1 + 0.8 * (total + 0.5*count(variables)) / V, 0.8, name, fontsize=14)
total += count(variables)
plt.plot([total - 0.5, total - 0.5], [0, C], color='grey')
plt.savefig('constraint-matrix.png', dpi=200)
V = 12833, C = 7875
CONSTRAINT SETS:
1 | one_control_center
41 | control_city_directly_connected
1681 | reduce_control_center_symmetry
41 | core_city_ub
1 | cycle_or_path
41 | disallow_core_tree
1 | exactly_nc_core_cities
41 | control_center_is_connected
4100 | is_connectable
205 | is_connected_timestep
41 | connected_graph
41 | conservation_of_flow
820 | force_edge_if_flow
820 | edge_cost_lb
VARIABLE SETS:
41 | is_control_center
820 | is_core_edge
41 | is_core_city
246 | is_connected_step
8405 | is_connectable_step
820 | flow
820 | abs_flow
820 | is_sub_edge
820 | edge_cost
autonomax.model.Params.timeLimit = 600.0
autonomax.model.optimize()
Changed value of parameter timeLimit to 600.0
Prev: inf Min: 0.0 Max: inf Default: inf
Gurobi Optimizer version 9.1.1 build v9.1.1rc0 (mac64)
Thread count: 8 physical cores, 8 logical processors, using up to 8 threads
Optimize a model with 7875 rows, 12833 columns and 40303 nonzeros
Model fingerprint: 0x4adcdf90
Model has 6 SOS constraints
Model has 820 general constraints
Variable types: 2460 continuous, 10373 integer (10373 binary)
Coefficient statistics:
Matrix range [1e+00, 2e+05]
Objective range [1e+00, 2e+04]
Bounds range [1e+00, 1e+02]
RHS range [7e-01, 4e+01]
Presolve removed 99 rows and 4366 columns
Presolve time: 0.14s
Presolved: 7776 rows, 8467 columns, 40168 nonzeros
Variable types: 2460 continuous, 6007 integer (6007 binary)
Found heuristic solution: objective 128227.28873
Root relaxation: objective 2.354143e+03, 4763 iterations, 0.17 seconds
Nodes | Current Node | Objective Bounds | Work
Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time
0 0 2354.14349 0 175 128227.289 2354.14349 98.2% - 0s
H 0 0 100960.17139 2354.14349 97.7% - 0s
0 0 4053.97421 0 275 100960.171 4053.97421 96.0% - 0s
H 0 0 30623.011882 4053.97421 86.8% - 1s
0 0 4418.33722 0 334 30623.0119 4418.33722 85.6% - 1s
0 0 4418.47503 0 331 30623.0119 4418.47503 85.6% - 1s
0 0 4418.51187 0 361 30623.0119 4418.51187 85.6% - 1s
0 0 4499.87977 0 391 30623.0119 4499.87977 85.3% - 1s
H 0 0 22776.355164 4499.87977 80.2% - 1s
0 0 4500.81515 0 342 22776.3552 4500.81515 80.2% - 1s
0 0 4500.81515 0 344 22776.3552 4500.81515 80.2% - 1s
0 0 4504.43885 0 405 22776.3552 4504.43885 80.2% - 1s
H 0 0 21758.497527 4504.43885 79.3% - 1s
0 0 4511.66543 0 356 21758.4975 4511.66543 79.3% - 1s
H 0 0 18827.019202 4511.66543 76.0% - 1s
0 0 4513.00320 0 355 18827.0192 4513.00320 76.0% - 1s
H 0 0 18768.544057 4513.00320 76.0% - 1s
0 0 4513.03559 0 357 18768.5441 4513.03559 76.0% - 1s
H 0 0 18721.583981 4513.03559 75.9% - 1s
0 0 4519.06648 0 336 18721.5840 4519.06648 75.9% - 1s
H 0 0 18667.481430 4519.06648 75.8% - 2s
0 0 4527.66139 0 340 18667.4814 4527.66139 75.7% - 2s
0 0 4527.70498 0 336 18667.4814 4527.70498 75.7% - 2s
H 0 0 18583.209259 4527.70498 75.6% - 2s
0 0 4529.80460 0 448 18583.2093 4529.80460 75.6% - 2s
0 0 4529.80460 0 411 18583.2093 4529.80460 75.6% - 2s
0 0 4530.70221 0 359 18583.2093 4530.70221 75.6% - 2s
0 0 4531.74381 0 348 18583.2093 4531.74381 75.6% - 2s
0 0 4531.98550 0 348 18583.2093 4531.98550 75.6% - 2s
H 0 0 18419.786870 4531.98550 75.4% - 2s
H 0 0 18389.786870 4531.98550 75.4% - 2s
0 0 4532.03971 0 380 18389.7869 4532.03971 75.4% - 2s
0 0 4532.13200 0 387 18389.7869 4532.13200 75.4% - 2s
0 0 4532.35006 0 432 18389.7869 4532.35006 75.4% - 2s
0 0 4532.35006 0 287 18389.7869 4532.35006 75.4% - 3s
H 0 0 18308.224113 4532.35006 75.2% - 3s
H 0 2 17896.244101 4532.35006 74.7% - 3s
0 2 4532.35006 0 281 17896.2441 4532.35006 74.7% - 3s
H 31 40 17871.860204 4819.61574 73.0% 711 4s
H 32 40 17869.696070 4819.61574 73.0% 700 4s
H 33 40 17864.053355 4819.61574 73.0% 682 4s
74 83 5958.17545 8 242 17864.0534 4819.61574 73.0% 437 5s
H 301 297 17646.627759 4819.61574 72.7% 202 7s
H 324 322 16992.028979 4819.61574 71.6% 197 7s
H 384 389 16956.245458 4819.61574 71.6% 183 7s
1163 1140 6487.41600 8 314 16956.2455 5101.30161 69.9% 131 10s
1449 1288 12783.6056 129 181 16956.2455 5133.62810 69.7% 132 15s
1462 1297 6750.03049 53 315 16956.2455 5133.62810 69.7% 131 22s
1465 1302 5133.62810 14 367 16956.2455 5133.62810 69.7% 157 26s
1478 1311 5133.62810 17 313 16956.2455 5133.62810 69.7% 161 30s
1539 1346 6050.22823 20 268 16956.2455 5133.62810 69.7% 173 35s
H 1544 1279 16956.245448 5133.62810 69.7% 173 35s
H 1545 1216 16956.245437 5133.62810 69.7% 173 35s
H 1546 1158 16956.245435 5133.62810 69.7% 173 35s
H 1581 1120 16456.992491 5133.62810 68.8% 178 37s
H 1617 1081 16439.212418 5133.62810 68.8% 178 38s
H 1666 1040 16403.524303 5133.62810 68.7% 182 39s
1684 1047 5946.08675 26 250 16403.5243 5133.62810 68.7% 181 40s
1974 1128 7430.91434 37 183 16403.5243 5133.62810 68.7% 191 45s
H 2485 1253 16403.524297 5133.62810 68.7% 194 49s
2537 1288 6437.59255 20 292 16403.5243 5133.62810 68.7% 195 50s
3171 1391 12788.4759 31 247 16403.5243 5707.89908 65.2% 197 55s
3731 1567 cutoff 29 16403.5243 5912.13645 64.0% 202 60s
H 3915 1500 16403.524284 5936.48380 63.8% 206 62s
4238 1625 15925.1481 29 132 16403.5243 6181.51878 62.3% 213 65s
4635 1816 13721.9076 34 227 16403.5243 6329.60823 61.4% 219 70s
4921 1973 12073.0263 27 246 16403.5243 6481.78741 60.5% 223 75s
H 4924 1973 16403.524266 6481.78741 60.5% 222 75s
H 4996 1973 16403.524252 6481.78741 60.5% 224 75s
H 5085 1981 16403.524218 6481.78741 60.5% 225 76s
H 5093 1981 16403.524203 6536.95583 60.1% 225 76s
H 5151 2051 16403.524201 6548.42423 60.1% 227 78s
H 5322 2086 16403.524157 6550.12403 60.1% 231 79s
H 5408 2086 16403.524148 6550.12403 60.1% 231 79s
5409 2180 15102.6718 22 393 16403.5241 6633.45060 59.6% 231 81s
H 5630 2216 16403.524131 6633.45060 59.6% 233 83s
H 5700 2210 16320.074675 6633.45060 59.4% 234 83s
H 5769 2270 16265.399568 6751.64795 58.5% 236 84s
5877 2357 8566.99998 41 172 16265.3996 6788.90418 58.3% 237 86s
6171 2505 10485.7343 31 178 16265.3996 6928.79627 57.4% 241 90s
H 6548 2607 16265.399540 7074.36271 56.5% 241 92s
H 6771 2691 16265.399522 7206.98333 55.7% 242 94s
6848 2782 9512.31074 36 190 16265.3995 7216.17296 55.6% 243 96s
7439 3129 11905.1467 69 133 16265.3995 7427.81777 54.3% 243 101s
8096 3467 14796.0865 47 171 16265.3995 7640.83057 53.0% 243 106s
8847 3841 15925.0756 82 172 16265.3995 7790.81816 52.1% 242 111s
H 8987 3841 16265.399360 7843.76620 51.8% 241 111s
9462 3971 15648.1280 27 173 16265.3994 7996.64763 50.8% 242 132s
H 9759 3971 16265.399355 8017.99594 50.7% 244 132s
9794 4159 13956.6795 40 137 16265.3994 8079.15858 50.3% 244 136s
H10257 4181 16265.399348 8146.29873 49.9% 244 139s
H10314 4181 16265.399325 8189.53473 49.7% 243 139s
10402 4364 12161.2472 43 140 16265.3993 8213.83056 49.5% 243 142s
H10629 4364 16265.399294 8224.77960 49.4% 243 142s
10907 4490 15382.1160 42 195 16265.3993 8249.64269 49.3% 244 145s
11667 4799 cutoff 37 16265.3993 8431.56400 48.2% 244 152s
H12271 4975 16265.399287 8545.95755 47.5% 244 156s
12728 5116 14805.1848 33 199 16265.3993 8659.89985 46.8% 243 160s
13482 5461 9449.79529 39 183 16265.3993 8775.02858 46.1% 243 168s
14088 5600 12775.0089 49 157 16265.3993 8862.34850 45.5% 242 173s
14650 5829 cutoff 31 16265.3993 8977.20181 44.8% 242 179s
15392 6050 15589.9351 38 133 16265.3993 9111.92676 44.0% 241 183s
16044 6301 cutoff 30 16265.3993 9197.09679 43.5% 241 187s
16709 6336 cutoff 32 16265.3993 9284.24523 42.9% 240 202s
16805 6578 15881.4301 40 93 16265.3993 9299.30495 42.8% 240 207s
17559 6739 14202.2732 32 174 16265.3993 9367.69827 42.4% 240 211s
18189 6912 11536.3438 60 140 16265.3993 9454.64159 41.9% 240 217s
18833 7165 11607.2751 37 195 16265.3993 9547.45918 41.3% 240 222s
19688 7218 10463.8150 23 215 16265.3993 9661.05263 40.6% 239 228s
19894 7430 14383.2953 29 286 16265.3993 9700.43778 40.4% 238 234s
20809 7702 cutoff 33 16265.3993 9767.61975 39.9% 238 239s
21769 7981 cutoff 36 16265.3993 9863.93203 39.4% 238 245s
22773 8168 14848.3101 37 205 16265.3993 9939.22640 38.9% 237 250s
23651 8312 10260.7946 32 262 16265.3993 10039.8212 38.3% 237 256s
24008 8607 13742.5118 30 338 16265.3993 10042.9903 38.3% 236 261s
24978 8895 11410.3250 34 277 16265.3993 10165.0069 37.5% 236 267s
25991 8944 12391.7154 28 194 16265.3993 10238.7663 37.1% 235 275s
H26006 8944 16265.399285 10238.7663 37.1% 235 275s
H26009 8944 16265.399281 10247.0449 37.0% 235 275s
H26023 8944 16265.399179 10247.4146 37.0% 235 275s
26145 9101 cutoff 39 16265.3992 10260.6933 36.9% 235 280s
26882 9298 12908.1776 31 172 16265.3992 10313.4583 36.6% 235 286s
27746 9519 11811.8469 24 267 16265.3992 10406.4679 36.0% 234 292s
28574 9749 14031.0354 32 236 16265.3992 10452.9440 35.7% 235 297s
29515 10021 16219.3824 30 215 16265.3992 10510.3985 35.4% 234 366s
30758 10127 12082.8638 37 202 16265.3992 10571.3201 35.0% 233 370s
31534 10379 15014.2418 88 70 16265.3992 10652.9914 34.5% 238 380s
32112 10463 15393.2837 48 139 16265.3992 10677.7296 34.4% 240 385s
32557 10546 15734.8321 37 257 16265.3992 10709.3618 34.2% 243 391s
32985 10603 15189.1443 33 184 16265.3992 10747.8844 33.9% 247 398s
33310 10736 14212.1987 25 271 16265.3992 10756.6034 33.9% 249 406s
33932 10840 14325.0567 44 191 16265.3992 10820.7750 33.5% 252 413s
34551 10849 13618.9087 32 257 16265.3992 10855.3175 33.3% 256 422s
H34795 10998 16265.398995 10885.6959 33.1% 258 431s
35320 11127 cutoff 29 16265.3990 10914.3803 32.9% 262 440s
35985 11218 infeasible 46 16265.3990 10933.4725 32.8% 266 465s
36472 11323 11698.6435 32 370 16265.3990 10969.2893 32.6% 268 476s
37060 11410 15888.0619 29 244 16265.3990 11023.9864 32.2% 272 485s
37681 11565 13303.9384 37 217 16265.3990 11049.0185 32.1% 276 494s
38319 11644 12493.8377 84 318 16265.3990 11085.8846 31.8% 280 503s
38780 11773 15233.7528 61 203 16265.3990 11107.2597 31.7% 282 512s
39462 11956 13168.1359 35 323 16265.3990 11148.2459 31.5% 286 521s
40108 12120 12360.9242 43 164 16265.3990 11170.6058 31.3% 289 531s
40823 12167 15860.9538 38 172 16265.3990 11224.3156 31.0% 293 542s
41181 12307 14683.4847 68 118 16265.3990 11241.6083 30.9% 294 552s
41954 12480 13471.3550 44 349 16265.3990 11279.5997 30.7% 298 562s
42698 12567 cutoff 34 16265.3990 11305.6808 30.5% 301 573s
43175 12722 13704.6962 44 211 16265.3990 11345.1290 30.2% 304 584s
44033 12779 15279.2714 47 151 16265.3990 11387.3869 30.0% 307 592s
44346 12872 cutoff 71 16265.3990 11407.2477 29.9% 308 600s
Cutting planes:
Gomory: 82
Cover: 619
Implied bound: 15
Clique: 1
MIR: 250
Flow cover: 932
GUB cover: 104
Inf proof: 22
Zero half: 163
RLT: 565
Relax-and-lift: 81
Explored 44748 nodes (13931369 simplex iterations) in 600.01 seconds
Thread count was 8 (of 8 available processors)
Solution count 10: 16265.4 16265.4 16265.4 ... 16403.5
Time limit reached
Best objective 1.626539899516e+04, best bound 1.143317660204e+04, gap 29.7086%
city_info = pd.DataFrame(autonomax.city_info())
city_info
| Index | Name | IsCoreCity | IsControlCenter | Demand | IngoingFlow | OutgoingFlow | |
|---|---|---|---|---|---|---|---|
| 0 | 0 | Boden | False | False | 4.5 | 4.000000e+00 | 8.500000e+00 |
| 1 | 1 | Borås | False | False | 0.7 | 1.610000e+01 | 1.680000e+01 |
| 2 | 2 | Eskilstuna | True | False | 1.1 | 7.000001e+00 | 8.100001e+00 |
| 3 | 3 | Falun | False | False | 2.3 | 2.202682e-13 | 2.300000e+00 |
| 4 | 4 | Gävle | False | False | 1.0 | 3.130000e+01 | 3.230000e+01 |
| 5 | 5 | Göteborg | False | False | 5.8 | 3.118392e-07 | 5.800000e+00 |
| 6 | 6 | Halmstad | False | False | 3.4 | 6.099999e+00 | 9.499999e+00 |
| 7 | 7 | Haparanda | False | False | 4.6 | 0.000000e+00 | 4.600000e+00 |
| 8 | 8 | Helsingborg | False | False | 2.2 | 3.899999e+00 | 6.099999e+00 |
| 9 | 9 | Hudiksvall | False | False | 3.9 | 2.740000e+01 | 3.130000e+01 |
| 10 | 10 | Jönköping | False | False | 1.2 | 1.680000e+01 | 1.800000e+01 |
| 11 | 11 | Kalmar | False | False | 4.0 | 0.000000e+00 | 4.000000e+00 |
| 12 | 12 | Karlskrona | False | False | 1.6 | 6.283449e-07 | 1.600001e+00 |
| 13 | 13 | Karlstad | False | False | 0.9 | 0.000000e+00 | 9.000000e-01 |
| 14 | 14 | Kiruna | False | False | 4.0 | 0.000000e+00 | 4.000000e+00 |
| 15 | 15 | Kristianstad | False | False | 3.0 | 2.131628e-13 | 3.000000e+00 |
| 16 | 16 | Lidköping | False | False | 1.2 | 7.600000e+00 | 8.800000e+00 |
| 17 | 17 | Linköping | True | False | 4.1 | 1.210000e+01 | 1.620000e+01 |
| 18 | 18 | Luleå | False | False | 2.0 | 1.310000e+01 | 1.510000e+01 |
| 19 | 19 | Malmö | False | False | 2.6 | 1.299999e+00 | 3.899999e+00 |
| 20 | 20 | Motala | True | False | 2.4 | 5.450000e+01 | 5.690000e+01 |
| 21 | 21 | Norrköping | True | False | 1.7 | 4.600000e+00 | 6.300000e+00 |
| 22 | 22 | Nyköping | False | False | 4.6 | 0.000000e+00 | 4.600000e+00 |
| 23 | 23 | Sandviken | False | False | 4.5 | 0.000000e+00 | 4.500000e+00 |
| 24 | 24 | Skellefteå | False | False | 4.4 | 1.510000e+01 | 1.950000e+01 |
| 25 | 25 | Skövde | False | False | 2.5 | 8.800000e+00 | 1.130000e+01 |
| 26 | 26 | Stockholm | False | False | 7.0 | 2.877698e-13 | 7.000000e+00 |
| 27 | 27 | Sundsvall | False | False | 0.7 | 2.670000e+01 | 2.740000e+01 |
| 28 | 28 | Trelleborg | False | False | 1.3 | 4.121148e-13 | 1.300000e+00 |
| 29 | 29 | Uddevalla | False | False | 4.0 | 7.069900e-13 | 4.000000e+00 |
| 30 | 30 | Umeå | False | False | 3.2 | 1.950000e+01 | 2.270000e+01 |
| 31 | 31 | Uppsala | False | False | 1.9 | 3.230000e+01 | 3.420000e+01 |
| 32 | 32 | Varberg | False | False | 0.8 | 9.499999e+00 | 1.030000e+01 |
| 33 | 33 | Vetlanda | False | False | 2.1 | 6.900000e+00 | 9.000000e+00 |
| 34 | 34 | Vänersborg | False | False | 3.6 | 4.000000e+00 | 7.600000e+00 |
| 35 | 35 | Västervik | False | False | 1.8 | 4.000000e+00 | 5.800000e+00 |
| 36 | 36 | Västerås | True | False | 1.4 | 4.910000e+01 | 5.050000e+01 |
| 37 | 37 | Växjö | False | False | 2.3 | 4.600000e+00 | 6.900000e+00 |
| 38 | 38 | Örebro | True | True | 4.1 | 1.083000e+02 | 4.263256e-13 |
| 39 | 39 | Örnsköldsvik | False | False | 3.1 | 2.270000e+01 | 2.580000e+01 |
| 40 | 40 | Östersund | False | False | 0.9 | 8.135714e-13 | 9.000000e-01 |
edge_info = pd.DataFrame(autonomax.edge_info())
edge_info
| From | To | Type | Flow | Cost | Distance | |
|---|---|---|---|---|---|---|
| 0 | Skellefteå | Umeå | SUB | 19.499999 | 731.139108 | 111 |
| 1 | Eskilstuna | Västerås | CORE | 8.100001 | 430.000000 | 43 |
| 2 | Gävle | Hudiksvall | SUB | -31.299999 | 1278.724508 | 118 |
| 3 | Norrköping | Nyköping | SUB | -4.600000 | 74.253949 | 58 |
| 4 | Linköping | Norrköping | CORE | -6.299999 | 440.000000 | 44 |
| 5 | Motala | Örebro | CORE | 56.900000 | 920.000000 | 92 |
| 6 | Karlskrona | Växjö | SUB | 1.600000 | 62.121900 | 102 |
| 7 | Boden | Kiruna | SUB | -4.000000 | 637.912972 | 291 |
| 8 | Sundsvall | Östersund | SUB | -0.900000 | 70.870188 | 166 |
| 9 | Eskilstuna | Stockholm | SUB | -7.000000 | 234.688115 | 101 |
| 10 | Halmstad | Helsingborg | SUB | -6.099999 | 145.447323 | 79 |
| 11 | Kalmar | Västervik | SUB | 4.000000 | 217.291833 | 139 |
| 12 | Umeå | Örnsköldsvik | SUB | 22.699999 | 849.479893 | 111 |
| 13 | Lidköping | Skövde | SUB | 8.800000 | 105.450189 | 49 |
| 14 | Karlstad | Örebro | SUB | 0.899999 | 29.229953 | 77 |
| 15 | Halmstad | Varberg | SUB | 9.499999 | 167.432207 | 65 |
| 16 | Lidköping | Vänersborg | SUB | -7.600000 | 121.696732 | 60 |
| 17 | Motala | Skövde | SUB | -11.299999 | 468.037910 | 118 |
| 18 | Uddevalla | Vänersborg | SUB | 4.000000 | 22.172756 | 21 |
| 19 | Hudiksvall | Sundsvall | SUB | -27.399999 | 641.652281 | 81 |
| 20 | Linköping | Motala | CORE | 16.200001 | 510.000000 | 51 |
| 21 | Sandviken | Västerås | SUB | 4.500000 | 174.172927 | 110 |
| 22 | Borås | Göteborg | SUB | -5.800000 | 119.727508 | 71 |
| 23 | Falun | Västerås | SUB | 2.300000 | 115.327746 | 128 |
| 24 | Linköping | Västervik | SUB | -5.800000 | 185.220774 | 97 |
| 25 | Sundsvall | Örnsköldsvik | SUB | -25.799999 | 1177.683824 | 127 |
| 26 | Jönköping | Motala | SUB | 18.000000 | 648.863591 | 108 |
| 27 | Vetlanda | Växjö | SUB | -6.900000 | 143.305416 | 72 |
| 28 | Borås | Varberg | SUB | -10.299999 | 260.758752 | 84 |
| 29 | Haparanda | Luleå | SUB | 4.600000 | 210.858567 | 124 |
| 30 | Luleå | Skellefteå | SUB | 15.099999 | 742.410209 | 133 |
| 31 | Kristianstad | Växjö | SUB | 2.999999 | 134.707632 | 120 |
| 32 | Motala | Vetlanda | SUB | -9.000000 | 456.419490 | 135 |
| 33 | Uppsala | Västerås | SUB | 34.199999 | 755.020104 | 78 |
| 34 | Gävle | Uppsala | SUB | 32.299999 | 484.711092 | 60 |
| 35 | Helsingborg | Malmö | SUB | -3.899999 | 67.318051 | 60 |
| 36 | Västerås | Örebro | CORE | 50.500001 | 930.000000 | 93 |
| 37 | Borås | Jönköping | SUB | 16.799999 | 404.484584 | 82 |
| 38 | Boden | Luleå | SUB | 8.500000 | 58.656838 | 32 |
| 39 | Malmö | Trelleborg | SUB | -1.299999 | 18.150073 | 34 |
| 40 | Eskilstuna | Norrköping | CORE | -0.000001 | 1020.000000 | 102 |
core_cost = sum(edge_info[edge_info['Type'] == 'CORE']['Cost'])
subnet_cost = sum(edge_info[edge_info['Type'] == 'SUB']['Cost'])
total_cost = core_cost + subnet_cost
print(f'core = {core_cost:>9.3f}')
print(f'subnet = {subnet_cost:>9.3f}')
print('------------------')
print(f'total = {total_cost:>9.3f}')
assert abs(autonomax.model.getObjective().getValue() - total_cost) < 1e-6
core = 4250.000 subnet = 12015.399 ------------------ total = 16265.399
visualization.show(pd.DataFrame(autonomax.city_info()), pd.DataFrame(autonomax.edge_info()))